import { defineStore } from "pinia";
import { ref, computed } from "vue";
import { listen } from "@tauri-apps/api/event";
import type { SipConfig, RegistrationStatus, ConnectionTestResult, TransportType, RegistrationEvent } from "../types";
import * as tauriApi from "../services/tauri-api";

export const useAuthStore = defineStore("auth", () => {
  // State
  const isLoggedIn = ref(false);
  const config = ref<SipConfig | null>(null);
  const registrationStatus = ref<RegistrationStatus>("Unregistered" as RegistrationStatus);
  const loading = ref(false);
  const error = ref<string | null>(null);
  const retryCount = ref(0);
  const maxRetries = ref(3);
  const nextRetryIn = ref<number | null>(null);
  const registrationMessage = ref<string | null>(null);
  const authFailureCount = ref(0);
  const maxAuthFailures = ref(3);
  const isAuthLocked = ref(false);
  const lastError = ref<string | null>(null);
  const serverResponse = ref<string | null>(null);
  const errorCode = ref<string | null>(null);
  
  // Event listener cleanup
  let unlistenRegistrationEvent: (() => void) | null = null;

  // Getters
  const isRegistered = computed(() => registrationStatus.value === "Registered");
  const isRegistering = computed(() => registrationStatus.value === "Registering");
  const hasError = computed(() => 
    registrationStatus.value === "Failed" || 
    registrationStatus.value === "AuthenticationFailed" ||
    registrationStatus.value === "NetworkError" ||
    registrationStatus.value === "TimeoutError"
  );
  const hasAuthError = computed(() => registrationStatus.value === "AuthenticationFailed");
  const hasNetworkError = computed(() => registrationStatus.value === "NetworkError");
  const hasTimeoutError = computed(() => registrationStatus.value === "TimeoutError");
  const canRetry = computed(() => retryCount.value < maxRetries.value && hasError.value && !isAuthLocked.value);
  const isRetrying = computed(() => retryCount.value > 0 && isRegistering.value);

  // Actions
  const login = async (sipConfig: SipConfig) => {
    loading.value = true;
    error.value = null;
    
    try {
      await tauriApi.login(sipConfig);
      config.value = sipConfig;
      isLoggedIn.value = true;
      registrationStatus.value = "Registered" as RegistrationStatus;
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Login failed";
      registrationStatus.value = "Failed" as RegistrationStatus;
      throw err;
    } finally {
      loading.value = false;
    }
  };

  const logout = async () => {
    loading.value = true;
    error.value = null;
    
    try {
      await tauriApi.logout();
      config.value = null;
      isLoggedIn.value = false;
      registrationStatus.value = "Unregistered" as RegistrationStatus;
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Logout failed";
      throw err;
    } finally {
      loading.value = false;
    }
  };

  const testConnection = async (
    server: string,
    port: number,
    transport: TransportType
  ): Promise<ConnectionTestResult> => {
    loading.value = true;
    error.value = null;
    
    try {
      const result = await tauriApi.testConnection(server, port, transport);
      return result;
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Connection test failed";
      throw err;
    } finally {
      loading.value = false;
    }
  };

  const updateRegistrationStatus = async () => {
    try {
      registrationStatus.value = await tauriApi.getRegistrationStatus();
    } catch (err) {
      console.error("Failed to update registration status:", err);
    }
  };

  const forceRetryRegistration = async () => {
    loading.value = true;
    error.value = null;
    
    try {
      await tauriApi.forceRetryRegistration();
    } catch (err) {
      error.value = err instanceof Error ? err.message : "Retry failed";
      throw err;
    } finally {
      loading.value = false;
    }
  };

  const getRetryInfo = async () => {
    try {
      const [currentRetryCount, currentMaxRetries] = await Promise.all([
        tauriApi.getRetryCount(),
        tauriApi.getMaxRetries(),
      ]);
      retryCount.value = currentRetryCount;
      maxRetries.value = currentMaxRetries;
    } catch (err) {
      console.error("Failed to get retry info:", err);
    }
  };

  const getAuthInfo = async () => {
    try {
      const [currentAuthFailures, currentMaxAuthFailures, authLocked, currentLastError] = await Promise.all([
        tauriApi.getAuthFailureCount(),
        tauriApi.getMaxAuthFailures(),
        tauriApi.isAuthenticationLocked(),
        tauriApi.getLastError(),
      ]);
      authFailureCount.value = currentAuthFailures;
      maxAuthFailures.value = currentMaxAuthFailures;
      isAuthLocked.value = authLocked;
      lastError.value = currentLastError;
    } catch (err) {
      console.error("Failed to get auth info:", err);
    }
  };

  const resetAuthFailures = async () => {
    try {
      await tauriApi.resetAuthFailures();
      authFailureCount.value = 0;
      isAuthLocked.value = false;
      lastError.value = null;
    } catch (err) {
      console.error("Failed to reset auth failures:", err);
      throw err;
    }
  };

  const clearError = () => {
    error.value = null;
    lastError.value = null;
    serverResponse.value = null;
    errorCode.value = null;
  };

  // Setup event listeners
  const setupEventListeners = async () => {
    try {
      unlistenRegistrationEvent = await listen<RegistrationEvent>("registration-event", (event) => {
        const registrationEvent = event.payload;
        
        // Update registration status
        registrationStatus.value = registrationEvent.status;
        registrationMessage.value = registrationEvent.message || null;
        
        // Update retry information
        if (registrationEvent.retry_count !== undefined) {
          retryCount.value = registrationEvent.retry_count;
        }
        if (registrationEvent.next_retry_in !== undefined) {
          nextRetryIn.value = registrationEvent.next_retry_in;
        }
        
        // Update error information
        if (registrationEvent.error_code) {
          errorCode.value = registrationEvent.error_code;
        }
        if (registrationEvent.server_response) {
          serverResponse.value = registrationEvent.server_response;
        }
        
        // Update login state based on registration status
        if (registrationEvent.status === "Registered") {
          isLoggedIn.value = true;
          loading.value = false;
          error.value = null;
          authFailureCount.value = 0;
          isAuthLocked.value = false;
        } else if (registrationEvent.status === "AuthenticationFailed") {
          error.value = registrationEvent.message || "Authentication failed";
          loading.value = false;
          isAuthLocked.value = true;
          // Update auth failure count
          getAuthInfo();
        } else if (registrationEvent.status === "NetworkError" || 
                   registrationEvent.status === "TimeoutError" ||
                   registrationEvent.status === "Failed") {
          error.value = registrationEvent.message || "Registration failed";
          loading.value = false;
        } else if (registrationEvent.status === "Unregistered") {
          isLoggedIn.value = false;
          loading.value = false;
          error.value = null;
          retryCount.value = 0;
          nextRetryIn.value = null;
          authFailureCount.value = 0;
          isAuthLocked.value = false;
        }
      });
    } catch (err) {
      console.error("Failed to setup registration event listener:", err);
    }
  };

  const cleanup = () => {
    if (unlistenRegistrationEvent) {
      unlistenRegistrationEvent();
      unlistenRegistrationEvent = null;
    }
  };

  // Initialize event listeners
  setupEventListeners();

  return {
    // State
    isLoggedIn,
    config,
    registrationStatus,
    loading,
    error,
    retryCount,
    maxRetries,
    nextRetryIn,
    registrationMessage,
    authFailureCount,
    maxAuthFailures,
    isAuthLocked,
    lastError,
    serverResponse,
    errorCode,
    
    // Getters
    isRegistered,
    isRegistering,
    hasError,
    hasAuthError,
    hasNetworkError,
    hasTimeoutError,
    canRetry,
    isRetrying,
    
    // Actions
    login,
    logout,
    testConnection,
    updateRegistrationStatus,
    forceRetryRegistration,
    getRetryInfo,
    getAuthInfo,
    resetAuthFailures,
    clearError,
    cleanup,
  };
});